package com.tmpt.freemarker.exec;

import com.googlecode.genericdao.search.Search;
import com.tmpt.dto.*;
import com.tmpt.freemarker.utils.FreemarkerUtils;
import com.tmpt.service.ITemplateService;
import com.tmpt.utils.StringUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created by wxy on 2017/1/28.
 */
public class FmUtils {

    private String datasource;

    public FmUtils(String datasource){
        this.datasource = datasource;
    }


    /**
     *
     * @param templateTable
     * @param dbcolumnsProperty {"table_name_column_name":{"table_name":"","column_name":"","data_type":"int","length":"0"},...}
     * @param columnList
     * @param columnCanAddList
     * @param columnNeedSumList
     * @param conditionColumnMapList
     * @param columnAliasMap 列对应的表的别名，如t1,t2
     * @param columnTableMap 多表时，通过列名找相应表名
     */
    public void dealColumnList(A1TemplateTableDto templateTable,Map<String,Map<String,String>> dbcolumnsProperty,
                               List<Map<String,Object>> columnList,
                               List<Map<String,Object>> columnCanAddList,
                               List<Map<String,Object>> columnNeedSumList,
                               List<Map<String,Object>>  conditionColumnMapList,Map<String,String> columnAliasMap,
                               Map<String,String> columnTableMap,List<A1TemplateColumnDto> templateTableColumnOptionList){
        List<A1TemplateColumnDto> a1TemplateColumnDtoList = templateTable.getA1TemplateColumnDtoList();
        for(A1TemplateColumnDto a1TemplateColumnDto : a1TemplateColumnDtoList){
            int deleteFlag = a1TemplateColumnDto.getDeleteFlag();
            if(deleteFlag==1){continue;}
            String columnName = a1TemplateColumnDto.getColumnName();
            String columnType = a1TemplateColumnDto.getColumnType();//页面查询字段用的
            String columnNameSql = a1TemplateColumnDto.getColumnNameSql();
            String propertyName = switch2Property(columnName);
            String defaultValue = a1TemplateColumnDto.getDefaultValue();
            String column_tableAliasName = a1TemplateColumnDto.getTableAliasName();
            String dataTransfer = a1TemplateColumnDto.getDataTransfer();
            dataTransfer = dataTransfer==null?"":dataTransfer;

            Map<String,String> columnTypeMap = columnTypeMap(columnTableMap,dbcolumnsProperty, columnName);
            String columnDbType = columnTypeMap.get("columnDbType");
            String columnType4MyBatis = columnTypeMap.get("columnType4MyBatis");
            String columnType4JavaEncap = columnTypeMap.get("columnType4JavaEncap");
            String columnDbTypeLower = columnDbType.toLowerCase();

            //Sum columns
            int needSum = a1TemplateColumnDto.getNeedSum();
            String columnNameSqlSum = a1TemplateColumnDto.getColumnNameSqlSum();

            //isquery
            int isQuery = a1TemplateColumnDto.getIsQuery();
            int dataResource = a1TemplateColumnDto.getDataResource();
            String optionsSql = a1TemplateColumnDto.getOptionsSql();
            String optionsPage = a1TemplateColumnDto.getOptionsPage();
            String queryType = a1TemplateColumnDto.getQueryType(); //eg: between,left like,right like,like,=
            queryType = queryType==null?"":queryType;
            String queryTypeLinkSign = queryType;
            String queryTypePlaceholder = "";
            if(!StringUtils.isNull(queryType)) {
                if (queryType.contains("like")) {
                    queryTypeLinkSign = "like";
                    queryTypePlaceholder = "模糊查询";
                }
            }else {
                queryTypeLinkSign = "=";
            }
            int hasOptions = 0;
            //String optionsDefaultKey = "";

            List<A1TemplateColumnOptionDto> optionDtoListCopy = new ArrayList<A1TemplateColumnOptionDto>();
            optionDtoListCopy.addAll(a1TemplateColumnDto.getA1TemplateColumnOptionDtoList());
            if(optionDtoListCopy.size()>0){
                //是多选项，页面显示select
                hasOptions = 1;
                //判断下有没有默认值：有=默认选择默认值，没有=默认选择全部（新加一个全部）
                //加“全部”
                String keyNameDefault = "";
                String valueNameDefault = "全部";
                A1TemplateColumnOptionDto optionDto = new A1TemplateColumnOptionDto();
                optionDto.setKeyName(keyNameDefault);
                optionDto.setValueName(valueNameDefault);
                optionDtoListCopy.add(0, optionDto);
            }

            //column alias
            String alias = columnAliasMap.get(columnName);
            String columnNameAlias = columnName;
            if (!StringUtils.isNull(alias)) {
                columnNameAlias = alias + "." + columnName;
            }

            //enum class name for option
            String tableName = templateTable.getTableName();
            //取表名作为类的前部分
            String tableName2classFirstWordUpper = firstWord2Upper(switch2Property(tableName));
            String columnName2classFirstWordUpper = firstWord2Upper(switch2Property(columnName));
            //生成enum类名
            String enumClassName = tableName2classFirstWordUpper+columnName2classFirstWordUpper;

            //列多选项
            for(A1TemplateColumnDto dtoTmp : templateTableColumnOptionList){
                String columnNameTmp = dtoTmp.getColumnName();
                if(columnNameTmp.equals(columnName)){
                    a1TemplateColumnDto.setA1TemplateColumnOptionJsonArray(dtoTmp.getA1TemplateColumnOptionJsonArray());
                    break;
                }
            }

            Map<String,Object > columnMap = new HashMap<String, Object>();
            columnMap.put("columnName",columnName);
            columnMap.put("propertyName",propertyName);
            columnMap.put("propertyNameFirstWordUpper",firstWord2Upper(propertyName));
            columnMap.put("columnShowName",a1TemplateColumnDto.getColumnShowName());
            columnMap.put("columnType",columnType);
            columnMap.put("columnTip",a1TemplateColumnDto.getColumnTip());
            columnMap.put("needSum", "" + needSum);
            columnMap.put("columnNameSql", columnNameSql);
            columnMap.put("columnNameFirstWordUpper",firstWord2Upper(columnName));
            columnMap.put("columnDbType",columnDbType);
            columnMap.put("columnType4JavaEncap",columnType4JavaEncap);
            columnMap.put("columnDbTypeLower",columnDbTypeLower);//Action,Model中属性类型
            columnMap.put("columnType4MyBatis", columnType4MyBatis);
            columnMap.put("isPrimaryKey", columnName.equalsIgnoreCase(templateTable.getPrimaryKey()) ? "true" : "false");
            columnMap.put("columnNameSqlSum",columnNameSqlSum);
            columnMap.put("dataResource", dataResource);
            columnMap.put("optionsSql", optionsSql);
            columnMap.put("optionsPage", optionsPage);
            columnMap.put("columnNameAlias", columnNameAlias);
            columnMap.put("column_tableAliasName", column_tableAliasName);
            columnMap.put("isQuery", isQuery);
            columnMap.put("queryType", queryType);
            columnMap.put("queryTypeLinkSign", queryTypeLinkSign);
            columnMap.put("queryTypePlaceholder", queryTypePlaceholder);
            columnMap.put("enumClassName", enumClassName);
            columnMap.put("enumClassNamefirstWord2Lower", firstWord2Lower(enumClassName));
            columnMap.put("enumClassNamefirstWord2Upper", firstWord2Upper(enumClassName));
            columnMap.put("a1TemplateColumnOptionJsonArray", a1TemplateColumnDto.getA1TemplateColumnOptionJsonArray());
            columnMap.put("a1TemplateColumnOptionDtoList", optionDtoListCopy);
            columnMap.put("defaultValue",defaultValue);
            columnMap.put("dataTransfer",dataTransfer);
            //UI
            columnMap.put("hasOptions", hasOptions);
            columnMap.put("defaultKey", defaultValue);
            columnList.add(columnMap);

            //can add/edit column
            int canAdd = a1TemplateColumnDto.getCanAdd();
            if(canAdd ==1){
                columnCanAddList.add(columnMap);
            }
            //sum
            if(needSum>=1){
                columnNeedSumList.add(columnMap);
            }
            //query condition
            if(isQuery==1) {
                conditionColumnMapList.add(columnMap);
            }
        }
    }


    private Map<String,String> columnTypeMap(Map<String,String> columnTableMap,Map<String,Map<String,String>> dbcolumnsProperty,String columnName){
        Map<String,String> map = new HashMap<String, String>();

        /*System.out.println("--------------------");
        System.out.println(columnName);
        System.out.println(columnTableMap.get(columnName));*/
        String dbColumnsPropertyKey = columnTableMap.get(columnName)+"_"+columnName;
        //System.out.println(dbcolumnsProperty);
        //多表关联时，这个列可能是其它表的，而dbcolumnsProperty是主表的，默认给varchar做数据展示
        String columnDbTypeTemp = "";
        if(!dbcolumnsProperty.keySet().contains(dbColumnsPropertyKey)){
            columnDbTypeTemp = "varchar";
        }else {
            columnDbTypeTemp = dbcolumnsProperty.get(dbColumnsPropertyKey).get("data_type");//数据库里的
        }
        String columnDbType = columnDbTypeTemp;
        String columnType4MyBatis = "";
        String columnType4JavaEncap = "";
        if(columnDbTypeTemp.equalsIgnoreCase("datetime") ||
                columnDbTypeTemp.contains("date")||
                columnDbTypeTemp.contains("timestamp")){
            columnDbType = "Timestamp";
            columnType4JavaEncap = "Timestamp";
            columnType4MyBatis = "TIMESTAMP";
        }else if(columnDbTypeTemp.equalsIgnoreCase("bigint")){
            columnDbType = "long";
            columnType4JavaEncap = "Long";
            columnType4MyBatis = "BIGINT";
        }else if(columnDbTypeTemp.equalsIgnoreCase("int")
                || columnDbTypeTemp.equalsIgnoreCase("integer")){
            columnDbType = "int";
            columnType4JavaEncap = "Integer";
            columnType4MyBatis = "INTEGER";
        }else if(columnDbTypeTemp.equalsIgnoreCase("double")
                || columnDbTypeTemp.equalsIgnoreCase("numeric")){
            columnDbType = "double";
            columnType4JavaEncap = "BigDecimal";
            columnType4MyBatis = "BigDecimal";
        }else if(columnDbTypeTemp.equalsIgnoreCase("varchar")
                || columnDbTypeTemp.equalsIgnoreCase("longtext")){
            columnDbType = "String";
            columnType4JavaEncap = "String";
            columnType4MyBatis = "VARCHAR";
        }else{
            columnDbType = "String";
            columnType4JavaEncap = "String";
            columnType4MyBatis = "VARCHAR";
        }

        map.put("columnDbType",columnDbType);
        map.put("columnType4MyBatis",columnType4MyBatis);
        map.put("columnType4JavaEncap",columnType4JavaEncap);
        return map;
    }


    /**
     * 整理合计字段 eg:sum(balance) ;
     * columnNameSqlSum 不存在时，使用拼接方法sum+(column)；
     * columnNameSqlSum 存在时，使用columnNameSqlSum字段 ，分以下两种情况处理:
     * needSum = 1时，使用拼接方法sum+(column);
     * needSum = 2时，columnNameSqlSum中可能是文字（eg:合计），直接使用
     * @param columnNeedSumList
     * @param sb4columnSumStr
     * @Param sumTitleList :eg:[{columnName:balancedate,title:合计},...]
        //eg:balancedate,合计
        Map<String,String> map = new HashMap<String, String>();
        map.put("columnName",columnName);
        map.put("title",columnNameSqlSum);
        sumTitleList.add(map);
     */
    public boolean dealNeedSumColumn(List<Map<String,Object>> columnNeedSumList, StringBuffer sb4columnSumStr,Map<String,String> sumTitleMap){
        boolean needSumBoolean = false;

        for(Map<String,Object > columnMap : columnNeedSumList) {
            String columnNameSqlSum = (String)columnMap.get("columnNameSqlSum");
            int needSum = Integer.parseInt((String) columnMap.get("needSum"));
            String columnName = (String)columnMap.get("columnName");


            if (!StringUtils.isNull(columnNameSqlSum)) {
                if (needSum == 2) {
                    //eg:balancedate,合计
                    sumTitleMap.put(columnName,columnNameSqlSum);
                    /*Map<String,String> map = new HashMap<String, String>();
                    map.put("columnName",columnName);
                    map.put("columnNameFirstWord2Upper",firstWord2Upper(columnName));
                    map.put("title",columnNameSqlSum);
                    sumTitleList.add(map);*/

                } else {
                    sb4columnSumStr.append(columnNameSqlSum).append(" as ").append(columnName).append(",");
                }
            } else {
                sb4columnSumStr.append("sum(").append(columnName).append(") as ").append(columnName).append(",");
            }
        }

        if(sb4columnSumStr.length()>1){
            sb4columnSumStr.deleteCharAt(sb4columnSumStr.length()-1);
        }

        return needSumBoolean;
    }


    /**
     * 整理可编辑列成字符串，mapper.xml中insert和update相关列使用字符串
     * @param columnCanAddList
     * @param sbCanAddColumn
     * @param sbCanAddColumnValue
     * @param sbCanEditColumn
     */
    public void dealCanEditColumn(List<Map<String,Object>> columnCanAddList, StringBuffer sbCanAddColumn,
                                  StringBuffer sbCanAddColumnValue,StringBuffer sbCanEditColumn){
        for(Map<String,Object > columnCanAddMap : columnCanAddList){
            String columnName = (String)columnCanAddMap.get("columnName");
            String propertyName = switch2Property(columnName);
            String columnType4MyBatis = (String)columnCanAddMap.get("columnType4MyBatis");
            sbCanAddColumn.append(columnName).append(",");
            sbCanAddColumnValue.append("#{").append(propertyName).append(",jdbcType=").append(columnType4MyBatis).append("},");
            sbCanEditColumn.append(columnName).append("=").append("#{").append(propertyName).append(",jdbcType=").append(columnType4MyBatis).append("},");
        }
        if(sbCanAddColumn.length()>1){
            sbCanAddColumn.deleteCharAt(sbCanAddColumn.length()-1);
            sbCanAddColumnValue.deleteCharAt(sbCanAddColumnValue.length()-1);
            sbCanEditColumn.deleteCharAt(sbCanEditColumn.length()-1);
        }
    }

    /**
     * 查询字段列 eg:select c1,c2,c3  mapper.xml中使用
     * @param columnList
     * @param sb4columnStr
     */
    public void dealColumnstr4Select(A1TemplateTableDto table, List<Map<String,Object>> columnList, StringBuffer sb4columnStr){
        for(Map<String,Object > columnMap : columnList){
            String columnName = (String)columnMap.get("columnName");
            //String columnType = columnMap.get("columnType");
            String columnDbType = ((String)columnMap.get("columnDbType")).toLowerCase();

            //生成columnNameSql
            String columnNameSql = (String)columnMap.get("columnNameSql");
            String tableAliasName = table.getTableAliasName();
            String columnTableAliasName = (String)columnMap.get("column_tableAliasName");
            //有可能本身有值，直接使用
            if(StringUtils.isNull(columnNameSql)){
                if(!StringUtils.isNull(columnTableAliasName)){
                    columnNameSql = columnTableAliasName+"."+columnName;
                }else if(!StringUtils.isNull(tableAliasName)){
                    columnNameSql = tableAliasName+"."+columnName;
                }
            }

            if(!StringUtils.isNull(columnDbType) && (columnDbType.equals("timestamp")||columnDbType.equals("datetime") )){
                //单表时，可能为空。select name from table1
                //多表时，可能不为空。select t1.name from table1 t1 ...
                if(StringUtils.isNull(columnNameSql)){//单表
                    sb4columnStr.append(columnName).append(",");
                }else {//多表
                    sb4columnStr.append(columnNameSql).append(" as ").append(columnName)/*.append("_Str")*/.append(",");
                }
            }else {
                //单表时，可能为空。select name from table1
                //多表时，可能不为空。select t1.name from table1 t1 ...
                if(StringUtils.isNull(columnNameSql)){//单表
                    sb4columnStr.append(columnName).append(",");
                }else {//多表
                    sb4columnStr.append(columnNameSql).append(" as ").append(columnName).append(",");
                }
            }
        }
        sb4columnStr.deleteCharAt(sb4columnStr.length()-1);
    }


    public String dealHiddenFiledsJson(A1TemplateTableDto templateTable){
        JSONArray jsonArray = new JSONArray();
        for(A1TemplateColumnDto column: templateTable.getA1TemplateColumnDtoList()){
            int dataResource = column.getDataResource();
            if(dataResource == A1TemplateColumnDto.dataResource_OptionsTable
                    || dataResource == A1TemplateColumnDto.dataResource_OptionsTableKeyEqualValue){
                if(column.getA1TemplateColumnOptionDtoList().size()>0){
                    String columnName = column.getColumnName();
                    A1TemplateColumnDto a1TemplateColumnDto = new A1TemplateColumnDto();
                    a1TemplateColumnDto.setColumnName(columnName);

                    for(A1TemplateColumnOptionDto option: column.getA1TemplateColumnOptionDtoList()){
                        long optionId = option.getId();
                        String keyName = option.getKeyName();
                        String valueName=option.getValueName();
                        A1TemplateColumnOptionDto a1TemplateColumnOptionDto = new A1TemplateColumnOptionDto();
                        a1TemplateColumnOptionDto.setId(optionId);
                        a1TemplateColumnOptionDto.setKeyName(keyName);
                        a1TemplateColumnOptionDto.setValueName(valueName);
                        a1TemplateColumnDto.getA1TemplateColumnOptionDtoList().add(a1TemplateColumnOptionDto);
                        JSONArray jsonArrayHidCol = new JSONArray();
                        for(A1TemplateColumnOptionHidColDto hiddenColumn:option.getA1TemplateColumnOptionHidColDtoList()){
                            String columName = hiddenColumn.getColumName();
                            JSONObject jsonObjectHidCol = new JSONObject();
                            jsonObjectHidCol.put("text", columName);
                            jsonArrayHidCol.add(jsonObjectHidCol);
                        }
                        JSONObject jsonObjectOption = new JSONObject();
                        jsonObjectOption.put("optionId",""+optionId);
                        jsonObjectOption.put("filedList",jsonArrayHidCol);
                        jsonArray.add(jsonObjectOption);
                    }
                }
            }
        }
        return jsonArray.toString();
    }

    /**
     * when data resource = 1 and 4, then option is from column itself
     * @param tableDto
     * @return
     */
    public List<Map> queryOption4ColumnSelfList(A1TemplateTableDto tableDto){
        List<Map> list = new ArrayList<Map>();

        String tableName = tableDto.getTableName();
        //取表名作为类的前部分
        String tableName2classFirstWordUpper = firstWord2Upper(switch2Property(tableName));
        //所有列
        List<A1TemplateColumnDto> columnDtoList = tableDto.getA1TemplateColumnDtoList();
        for(A1TemplateColumnDto columnDto : columnDtoList){
            int dataSource = columnDto.getDataResource();
            //只取dataResource_OptionsTable = 1
            //dataResource_OptionsTableKeyEqualValue = 4
            if(dataSource!=1 && dataSource!=4){continue;}
            //没option数据不处理
            if(columnDto.getA1TemplateColumnOptionDtoList().size()==0){continue;}
            String columnName = columnDto.getColumnName();
            String propertyName = switch2Property(columnName);
            String columnName2classFirstWordUpper = firstWord2Upper(propertyName);
            //生成enum类名
            String className = tableName2classFirstWordUpper+columnName2classFirstWordUpper;
            List<A1TemplateColumnOptionDto> columnOptionDtoList = columnDto.getA1TemplateColumnOptionDtoList();
            List<A1TemplateColumnOptionDataDto> columnOptionDataDtoList = new ArrayList<A1TemplateColumnOptionDataDto>();
            for(A1TemplateColumnOptionDto optionDto:columnOptionDtoList){
                A1TemplateColumnOptionDataDto optionDataDto = new A1TemplateColumnOptionDataDto();
                optionDataDto.setOptionId(optionDto.getId());
                optionDataDto.setOptionName(optionDto.getOptionName()==null?"":optionDto.getOptionName());
                optionDataDto.setKeyName(optionDto.getKeyName());
                optionDataDto.setValueName(optionDto.getValueName());
                columnOptionDataDtoList.add(optionDataDto);
            }
            Map map = new HashMap();
            map.put("className",className);
            map.put("propertyName",propertyName);
            map.put("propertyNameFirstWord2Upper",columnName2classFirstWordUpper);
            map.put("columnOptionDataDtoList", columnOptionDataDtoList);
            list.add(map);
        }

        //genOptionEnumFile4ColumnSelf(list);

        return list;
    }

    /**
     * 生成ftl文件
     * @param list
     */
    public void genOptionEnumFile4ColumnSelf(List<Map> list){
        for (Map map : list) {
            Map map1 = new HashMap();
            map1.put("className",map.get("className"));
            map1.put("columnOptionDataDtoList",map.get("columnOptionDataDtoList"));
            genEnum(map1,map.get("className").toString());
        }
    }

    /**
     * 数据字典生成出来
     * @param templateService
     * @return map是一列的options
     */
    public List<Map> queryOptionDataListBySearch(ITemplateService templateService){
        List<String> columnNameList = new ArrayList<String>();
        {
            Search search = new Search();
            List<A1TemplateColumnOptionDataDto> columnOptionDataDto = templateService.queryOptionDataListBySearch(search);
            for (A1TemplateColumnOptionDataDto optionDataDto : columnOptionDataDto) {
                String columnName = optionDataDto.getColumnName();
                if (!columnNameList.contains(columnName)) {
                    columnNameList.add(columnName);
                }
            }
        }
        List<Map> list = new ArrayList<Map>();
        {
            for (String columnName : columnNameList) {
                Search search = new Search();
                search.addFilterEqual("columnName", columnName);
                search.addSort("sort", false);
                String className = firstWord2Upper(switch2Property(columnName));
                List<A1TemplateColumnOptionDataDto> columnOptionDataDtoList = templateService.queryOptionDataListBySearch(search);
                for(A1TemplateColumnOptionDataDto optionDataDto : columnOptionDataDtoList){
                    optionDataDto.setOptionId(0L);
                    System.out.println(optionDataDto.getColumnName());
                }
                Map map = new HashMap();
                map.put("className",className);
                map.put("columnOptionDataDtoList", columnOptionDataDtoList);
                list.add(map);
            }
        }
        return list;
    }

    /**
     * 生成ftl文件
     * @param list
     */
    public void genOptionDataEnumFile(List<Map> list){
        for (Map map : list) {
            Map map1 = new HashMap();
            map1.put("className",map.get("className"));
            map1.put("columnOptionDataDtoList",map.get("columnOptionDataDtoList"));
            genEnum(map1,map.get("className").toString());
        }
    }


    /**
     * 按模板生成各种文件
     * @param map
     * @param type=1：生成web层；type=2：生成service层; type=3:生成所有
     */
    public void genFile(Map map, int type){
        String classNameFirstWordUpper = (String)map.get("classNameFirstWordUpper");
        String classNameFirstWordLower = (String)map.get("classNameFirstWordLower");

        if(type==1 || type==3) {
            //pages
            genTeptJsp(map, classNameFirstWordLower);
            genTeptAddJsp(map, classNameFirstWordLower);
            //genTeptAddJs(map, classNameFirstWordLower);
            genTeptDataJs(map, classNameFirstWordLower);
            genConditionJsp(map, classNameFirstWordLower);
            //genConditionJs(map, classNameFirstWordLower);
            //genMyJs(map, classNameFirstWordLower);
            //生成action
            genAction(map, classNameFirstWordUpper);
            //生成tag
            genTag(map, classNameFirstWordUpper);
        }

        if(type==2 || type==3) {
            //TmptMapper.java
            genMapperDao(map, classNameFirstWordUpper);
            //Tmpt.java
            genMapperModel(map, classNameFirstWordUpper);
            //TmptDto.java
            genMapperModelDto(map, classNameFirstWordUpper);
            //Mapper.xml
            genMapperXml(map, classNameFirstWordUpper);
            //TmptService.java
            genServiceImpl(map, classNameFirstWordUpper);
            //ITmptService.java
            genServiceApi(map, classNameFirstWordUpper);
            //struts.xml
            genStrutsXml(map);
            //dubbo-service.xml
            genDubboServiceXml(map);
            //dubbo-consume-tmpt.xml
            genDubboConsumeXml(map);
            //dozer.xml
            genDozerXml(map, classNameFirstWordUpper);
        }
    }

    //开发环境工作区目录
    //private String workspacePath = "E:\\workspace-agri\\";
    //private String workspacePath = "/Users/wxy/workspace/mybird-old";


//    //MAC
//    private String projectFtl ="/Users/wxy/workspace/mybird-old/bird/";
//    private String projectWeb ="/Users/wxy/workspace/mybird-old/bird/";
//    private String projectBiz ="/Users/wxy/workspace/mybird-old/birdbiz/";

    private String basePath="D://sourcetree/gitee/";
    //Windows
    private String projectFtl = basePath+"bird-struts2/";
    private String projectWeb = basePath+"bird-struts2/";
    private String projectBiz = basePath+"birdbiz-struts2/";



    private void genDozerXml(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"model"+ File.separator;
        String pathOut = projectBiz+"birdbiz-web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"resources"+ File.separator+"dozer-config"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("TmptDozer.xml.ftl", map, "dozer"+fileNamePre + ".xml");
    }
    private void genServiceImpl(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"service"+ File.separator;
        String pathOut = projectBiz+"birdbiz-web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"service"+ File.separator+"impl"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("TmptService.java.ftl", map, fileNamePre + "Service.java");
    }
    private void genServiceApi(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"api"+ File.separator;
        String pathOut = projectBiz+"birdbiz-api"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"service"+ File.separator+"intf"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("ITmptService.java.ftl", map, "I" + fileNamePre + "Service.java");
    }
    private void genMapperDao(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"mapper"+ File.separator;
        String pathOut = projectBiz+"birdbiz-web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"mapper"+ File.separator;
        /*if(this.datasource.equals("dsB")){
            pathOut = projectBiz+"birdbiz\\birdbiz-web\\src\\main\\java\\com\\tmptSource\\mapperbiz\\";
        }*/
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("TmptMapper.java.ftl", map, fileNamePre + "Mapper.java");
    }
    private void genMapperModel(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"model"+ File.separator;
        String pathOut = projectBiz+"birdbiz-web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"bean"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("Tmpt.java.ftl", map, fileNamePre + ".java");
    }
    private void genMapperModelDto(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"model"+ File.separator;
        String pathOut = projectBiz+"birdbiz-api"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"dto"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("TmptDto.java.ftl", map, fileNamePre + "Dto.java");
    }
    private void genMapperXml(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"mapper"+ File.separator;
        String pathOut = projectBiz+"birdbiz-web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"resources"+ File.separator+"mapper"+ File.separator;
        /*if(this.datasource.equals("dsB")){
            pathOut = projectBiz+"birdbiz-web\\src\\main\\resources\\mapperbiz\\";
        }*/
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("TmptMapper.xml.ftl", map, fileNamePre + "Mapper.xml");
    }

    private void genAction(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+
                File.separator+"action"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+
                File.separator+"tmptSource"+ File.separator+"controller"+ File.separator+"action"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("TmptAction.java.ftl", map, fileNamePre + "Action.java");
    }

    private void genTag(Map map, String fileNamePre){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"action"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"controller"+ File.separator+"taglib"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("TmptTag.java.ftl", map, fileNamePre + "Tag.java");
    }

    private void genStrutsXml(Map map){
        //String pathFtl = workspacePath+projectWeb+"web\\src\\main\\webapp\\freemarker\\biz\\action\\";
        //String pathOut = workspacePath+projectWeb+"web\\src\\main\\resources\\";
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"action"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"resources"+ File.separator;

        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("struts.xml.ftl", map, "coding/struts-coding.xml");
    }
    private void genDubboServiceXml(Map map){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"dubbo"+ File.separator;
        String pathOut = projectBiz+"birdbiz-web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"resources"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("dubbo-service-coding.xml.ftl", map, "coding/dubbo-service-coding.xml");
    }

    private void genDubboConsumeXml(Map map){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"dubbo"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"resources"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("dubbo-consume-coding.xml.ftl", map, "coding/dubbo-consume-coding.xml");
    }

    private void genTeptJsp(Map map, String tableName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"page"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"admin123"+ File.separator+"coding"+ File.separator+tableName+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("my.jsp.ftl", map,"my.jsp");
    }
    private void genTeptAddJs(Map map, String tableName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"page"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"admin123"+ File.separator+"coding"+ File.separator+""+tableName+File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("add_edit.js.ftl", map,"add_edit.js");
    }

    private void genTeptAddJsp(Map map, String tableName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"page"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"admin123"+ File.separator+"coding"+ File.separator+tableName+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("add_edit.jsp.ftl", map,"add_edit.jsp");
    }


    private void genTeptDataJs(Map map, String tableName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"page"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"admin123"+ File.separator+"coding"+ File.separator+""+tableName+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("data.js.ftl", map,"data.js");
    }
    private void genConditionJsp(Map map, String tableName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"page"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"admin123"+ File.separator+"coding"+ File.separator+tableName+File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("condition.jsp.ftl", map, "condition.jsp");
    }
    private void genConditionJs(Map map, String tableName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"page"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"admin123"+ File.separator+"coding"+ File.separator+tableName+File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("condition.js.ftl", map, "condition.js");
    }
    private void genMyJs(Map map, String tableName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"page"+ File.separator;
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"admin123"+ File.separator+"coding"+ File.separator+tableName+File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("my.js.ftl", map, "my.js");
    }

    //
    private void genEnum(Map map, String ClassName){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"model"+ File.separator;
        String pathOut =projectBiz+"birdbiz-api"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"enums"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("enum.java.ftl", map, ClassName+".java");
    }
    public void genEnumTag(Map map){
        String pathFtl = projectFtl+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"webapp"+ File.separator+"freemarker"+ File.separator+"biz"+ File.separator+"action"+ File.separator+"";
        String pathOut = projectWeb+"web"+ File.separator+"src"+ File.separator+"main"+ File.separator+"java"+ File.separator+"com"+ File.separator+"tmptSource"+ File.separator+"controller"+ File.separator+"taglib"+ File.separator;
        FreemarkerUtils fmUtils = new FreemarkerUtils(pathFtl,pathOut);
        fmUtils.fprint("A1EnumTag.java.ftl", map, "A1EnumTag.java");
    }



    //==================================================
    //                  工具类
    //==================================================
    public static String firstWord2Upper(String str){
        String firstWord = str.substring(0,1).toUpperCase();
        String str1 = firstWord + str.substring(1);
        return str1;
    }

    public static String firstWord2Lower(String str){
        String firstWord = str.substring(0,1).toLowerCase();
        String str1 = firstWord + str.substring(1);
        return str1;
    }

    // Bean --> Map 1: 利用Introspector和PropertyDescriptor 将Bean --> Map
    public static Map<String, Object> transBean2Map(Object obj) {

        if(obj == null){
            return null;
        }
        Map<String, Object> map = new HashMap<String, Object>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor property : propertyDescriptors) {
                String key = property.getName();

                // 过滤class属性
                if (!key.equals("class")) {
                    // 得到property对应的getter方法
                    Method getter = property.getReadMethod();
                    Object value = getter.invoke(obj);

                    map.put(key, value);
                }

            }
        } catch (Exception e) {
            System.out.println("transBean2Map Error " + e);
        }

        return map;

    }



    /**
     * 字段转成属性
     * @param columnName
     * @return
     */
    public static String switch2Property(String columnName){
        //System.out.println(columnName.matches("c+"));
        if (columnName.contains("_")){
            Pattern pattern = Pattern.compile("_[a-z,0-9]");
            Matcher matcher = pattern.matcher(columnName);
            while(matcher.find()){
                String old = matcher.group();
                String new1 = matcher.group().toUpperCase();
                columnName = columnName.replaceAll(old, new1.replace("_",""));
            }
        }
        return columnName;
    }


    /**
     * 属性转字段
     * @param property
     * @return
     */
    public static String switch2Column(String property){
        if (property.matches("[a-z]+[A-Z][a-z]+([A-Z][a-z]+)*")) {
            Pattern pattern = Pattern.compile("[A-Z]");
            Matcher matcher = pattern.matcher(property);
            while(matcher.find()){
                String old = matcher.group();
                System.out.println(old);
                String ne = matcher.group().toLowerCase();
                property = property.replaceAll(old, "_"+ne);
            }
        }
        return property;
    }


}
